
AUX


a.dly(Integer)

  'Integer'     is a count of milliseconds to pause for a while.

  This is unconditional. It waits, it times out, then the next instruction is done. It is useful if
  a prompt needs to appear for a moment but not persist to clutter the screen. In this case, cursor
  position would be stored before printing the prompt so c.pos() can reset the position and c.put()
  can print spaces to overwrite the prompt.


a.key(Press)

  'Press'       is the key pressed to end an unconditional wait.

  This is much faster and easier to use than c.get() if a single keypress is all that is needed to
  determine what happens next.


a.msg(Text,Title,Style)

  'Text'        is the text of a standard Windows messagebox.
  [Title]       is the text displayed on the messagebox title bar.
  [Style]       sets the icons and buttons used on a messagebox.

  The text and title can be a string, or a number, or nil. The expected results will be printed.
  The title and style arguments can be omitted, if all that is needed is a simple text message.
  There are no Lua standards for style names, but they are defined in the C header "Winuser.h",
  where searching for "MB_OK" will find the styles that can be used. It is best to consult a Win32
  API reference for details on the meanings and available styles. Pass them as a number to combine
  the values wanted. It's tedious but it works. The default is MB_OK, which equals 0. Use this 0
  or omit it entirely if there is no need to do otherwise.


a.utc()

  This function takes no arguments. It returns a count of seconds since the start of 01/01/1970.
  UTC is Coordinated Universal Time, a measure independent of location, timezone, daylight saving,
  or any other offsets that may be applied. UTC can also be considered as a Unix Time Counter. Its
  data is intended to drive a clock mechanism, which combined with appropriate offsets, can show
  the correct time in a large number of specific conditions.


a.clk(Table)

  'Table'       is an array of clock parameters and a Unix timestamp.

  If Table[0] is a Unix timestamp measuring seconds before or after the start of 1970, the output
  is a clock with year, month, day, hour, minute, and second, stored in descending order in table
  elements 1~6, with day of the week (1~7 = Sun~Sat) in Table[7] and day of the year in Table[8].

  If Table[0] is nil, the first 6 parameters must be entered for a date and time in the Gregorian
  calendar. The output will be a Unix timestamp that replaces the nil that was previously there.

  This raw data can be presented as text using Lua's string.format(), or the numbers are directly
  applied in calculations. Any count of seconds before or after the start of 01/01/1970 can get an
  appropriate output, over a range of thousands of years, past or future. The limit is defined by
  a 'Lua number', which means a double precision floating point number where 52 bits can hold the
  integer count of seconds without error. The limit is absolute, regardless of polarity.

  The offset must be adjusted externally, but it saves a lot of inconvenience because the function
  adjusts all parameters based on one input value, so the correct data can be displayed with less
  calculation than Lua would have to do if the offset were detected and passed back. Also, it may
  not be possible to get it from the host system, in which case it would have to be overridden by
  manual input. A similar case is found when an NNTP server supplies the time, and an offset for
  daylight saving time must be added later. By returning UTC plus an offset programmed in Lua, the
  best compromise in efficiency and versatility is achieved, with the difficult calculation being
  done by C code which is faster than Lua.


a.lyr(Year)

  'Year'        is the year number to test for being a leap year.

  This function will return a 1 if the year being tested is a leap year, otherwise it returns nil.
  The a.clk() function depends on an internal leap year indicator to calculate when the count of
  seconds in a leap day is to be added or subtracted from a Unix timestamp. The internal function
  is extremely fast, so it's offered here to save time if Lua code needs to test for leap years.


a.tab(String,Separator)

  'String'      is a text string to be converted to an indexed table.
  [Separator]   is a string with one character, to cut the input text.

  The a.tab() function returns a table, converted from the string passed to it, using the separator
  passed to it as its second argument. It inverts the action of the a.str() function. The separator
  is passed as a string to keep the syntax clean and compact, but only the first character is used.
  If the separator is omitted, or is empty, the entire input string is copied into table element 1.
  The table is an indexed array with no gaps. The a.tab() function is intended to be an inverse of
  Lua's string.concat() function, but a more precisely complementary pair of functions is needed to
  get fast, accurate conversion to a form more easily used with other tools. Example: a CSV file is
  likely to have several lines, each with comma-separated fields. This function can convert the CSV
  file to an array of lines, then used in an iterator to change each element to an array of indexed
  fields. Lua's io.lines() function can do this but it is not available in all versions of Lua used
  in LuaTools, and a faster and exactly complementary system to convert between strings and indexed
  arrays is often needed, and it's here in a single library file that can be used in all versions.


a.str(Table,Separator)

  'Table'       is an indexed table to be converted to a text string.
  [Separator]   is a string with one character, to join the output text.

  The a.str() function returns a string, converted from the table passed to it, using the separator
  passed to it as its second argument. It inverts the action of the a.tab() function. The separator
  is passed as a string to keep the syntax clean and compact, but only the first character is used.
  If the separator is omitted, there will be no separation (equivalent to passing an empty string).
  Lua's table.concat() function will do this but these two conversion functions are designed to be
  fast, simple, and exactly reciprocal to each other, to edit text files and comma-separated arrays
  or for any other need to convert data quickly between a string and a numerically indexed table. A
  table must have no gaps in it. The function uses 'getn' internally to determine its length. If a
  separator exists at the end, or not, this condition will be preserved across conversions. A final
  separator becomes an empty string in the last non-nil table element. It is best to avoid adding a
  key-value pair to the table, this function expects a table to be used as a simple array. It does
  not do as much error-checking as table.concat() does, but it has the advantage of being available
  in the same library file in all three Lua versions used in LuaTools, as well as being designed as
  an exact inverse of a.str().


a.raw(HEX)

  'HEX'         is a string of HEX digit pairs to convert to raw data.

  The a.raw() function returns a string of raw bytes directed by pairs of hexadecimal digits in the
  input string. It also returns a byte count, and if an error was found in a character, the second
  return value is negative, its absolute value indicating where the error occurred. The function is
  very fast, but also accepts upper or lower case while accurately detecting any character that is
  not a hexadecimal digit. The 'tonumber()' Lua function can be used to do this but it is complex,
  and is designed to handle larger numbers in a single conversion. (See also the a.int() function.)
  The a.raw() function takes multiple digit pairs, as a way to build large arrays of raw bytes from
  data or code in text form to avoid complications with control characters and 'escape' codes.


a.hex(Data)

  'Data'        is a string of raw bytes to convert to hex digit pairs.

  The a.hex() function returns a string of hexadecimal digit pairs as an ASCII text encoding of the
  raw bytes in the input string. It inverts the action done by the a.raw() function. The output is
  upper case. The a.num() function could also be used in an iterator that passed each character to
  it as an integer expressing its byte value, but that is extremely inefficient! Use a.num() when a
  single integer, especially a large one, needs converting to a HEX numeral.


a.div(Numerator,Divisor,ModFlag)

  'Numerator'   is the integer value to be divided.
  'Divisor'     is the integer that does the division.
  [ModFlag]     determines how the remainder is set.

  This function returns a quotient and a remainder like the DIV machine code instruction. It is not
  as fast but it is still much faster than it would be to write it in Lua. It uses one division and
  one multiplication for 32-bit integers. Various Lua versions have had MOD functions, and recently
  a MOD operator %, but with very inconsistent methods! Some mix integer and floating point, others
  differ in the rounding used, and the % operator in recent Lua versions is NOT the same as C's mod
  operator! This may well change yet again.

  The a.div() function is efficient, versatile, and consistent for all three Lua versions supported
  by LuaTools. The remainder is returned as a second value, and the optional 'ModFlag' argument can
  be used to determine whether the numerator scale is considered bipolar or unipolar. If set to nil
  or 0, or it is omitted, normal bipolar action is used. Any nonzero setting sets unipolar action.

  Bipolar scale is the normal method, it takes zero as the centre, and rounds toward that zero, and
  the remainder takes the sign of the numerator, and if the numerator is stepped and passes through
  zero, the remainder will change polarity and its absolute value will appear to change direction.

  Unipolar scale is the alternative. It uses zero as a datum, but the datum could have been another
  number. The numerator is rounded toward the negative end of a scale. The remainder takes the sign
  of the divisor, not the numerator. If the numerator steps downward, the remainder steps downward.
  The remainder does not change polarity when the numerator passes through zero.

  Electronics engineers may recognise normal action as like a potentiometer with a central terminal
  on the track, anchored to ground, with unipolar action being more like that of a rotary encoder.

  Lua's '%' operator added in Lua v5.2 is unipolar. C's % operator and Lua's MOD function (recently
  renamed as FMOD) are bipolar. The a.div() function can be either. It is not intended to replace a
  Lua function, and will not use floating point Lua numbers even though the return values take that
  form as is standard in Lua. It strictly intended for fast integer calculation because Lua has not
  had this ability as standard, and even now it may be inconsistent between versions.


a.bit(Integer,Operator,Integer)

  'Integer'     is a number (whose fractional part will be ignored).
  'Operator'    is a standard bit logic operator, as a string.
  'Integer'     is a number to be logically combined with the first number.

  This function returns a 32-bit integer as a Lua number. The input may be signed or unsigned, but
  the inputs will be processed as unsigned, and the output will be unsigned. If an input is larger
  than a 32-bit integer can hold, the higher bits will be ignored. This function is intended to be
  a fast method of doing things normally available in 32 bit C code. It is NOT designed to use all
  the bits in a 'Lua number' which uses 52 bits ('mantissa' of double precision floating point) to
  represent a gapless range of integer values.

  There are five operators: '&' (AND), '|' (OR), '^' (XOR), '<<' (LEFT SHIFT), '>>' (RIGHT SHIFT).
  NOT is also possible, as N^-1. Each operator is passed as a string. If it is invalid, the output
  is nil. The first character of the operator string is used. Any others will be ignored.


a.int(Numeral,Base)

  'Numeral'     is a string of numeric digits with optional formatting.
  [Base]        is an optional number base from 2~36, defaulting to 10.

  This function returns a 32-bit integer as a Lua number. The input may be signed or unsigned, and
  it returns a number, or nil, in which case the second returned value reports either -1 indicating
  overflow, or a positive number that indexes the first character considered bad during the attempt
  to convert the string to an integer. A third value is returned, giving the intended polarity of a
  numeral. This is NOT the same as signed or unsigned data type, it is an indicator of the intent,
  something that can never be deduced from a stored integer type. This will not affect the internal
  representation after a numeral is converted to a number, but it can be very useful when restoring
  a number to a formatted and printed numeral later, using the a.num() function. Indicating that a
  numeral should be considered signed (bipolar) is often important in programs used for engineering
  calculations. The polarity indicator allows the user to specify an integer as signed or unsigned,
  which in turn allows better error-checking and for the intent to be carried over to final output
  or to be a more convenient way to test the polarity for other purposes. 0 means unsigned, and an
  absolute value of 1 is signed, with the actual polarity being expressed as +1 or -1.

  Letter-based digits (and base specifier inputs) are case insensitive. There is no formatting for
  scientific or engineering notation, and there is no floating point. A decimal point is an error.

  The default number base is decimal, but this may be overridden with a base specifier as follows:
  /b is binary, /o is octal, /d is decimal (redundant in this case), and /x is hexadecimal. A base
  specifier must be written before the first digit, and if any digit is too large for the specified
  base, it is an error, and its location in the string is given by the second return value. Always
  take care when using base specifiers. If the trigger character '/' is not immediately followed by
  a valid base code, the results will not be reliably defined.

  The default base can be changed by the second argument if used, but the override in the numeral
  string is always the highest priority setting for a number base.

  Apart from plus or minus signs, some other characters can be present. Commas can be used as digit
  separators, as can underscores, and spaces, and all will be ignored, as will any leading zeros.

  Signed values are checked for overflow because internally there is no difference between a large
  unsigned value, and a negative signed value. This test helps reduce the chance of error when data
  is entered by hand, or when copied from existing text. A plus or minus sign may be written after
  the digits as well as before, so that unusual conventions in ledgers or other tables may be used,
  but either way there must be no more than ONE in any numeral. If there is a second, anywhere, the
  second sign will be ignored. Once a signed number is returned to Lua, it can be considered safe.
  In some cases an unsigned overflow will not be detected, but this is a limit of C, the language
  Lua is built with. It would need assembly language to read the carry flag to eliminate this risk
  entirely, or using the mantissa of a double precision float to allocate more than 32 bits, but a
  slight risk is better than slowing down every operation.


a.num(Integer,Base,Signed)

  'Integer'     is an integer to be interpreted as signed or unsigned.
  [Base]        is an optional number base from 2~36, defaulting to 10.
  [Signed]      modifies the output string for signed/unsigned interpretation.

  This function is the inverse of a.int(). Its output, used in that function, will return the same
  integer given to this one. The Lua number is processed as a 32 bit integer with an assumption of
  unsigned, so it is necessary to indicate the intent. Specify a non-nil value as a third argument
  if you want the numeral to be written as a signed integer.

  The number base defaults to 10 if the second argument is omitted, but as with a.int(), a.num{} is
  able to use any specified number base between 2 and 36. The output is always upper case.




----------------------------------------------------------------------------------------------------

CONSOLE


c.att(0xXX)

  '0xXX'        is a integer, but it helps with explanations.

  The number is a pair of 'attributes'. It is less than 256, with the first hexadecimal 'nybble'
  (0~F) defining background colour in each character block in the console window, and the second
  defining text colour. Experiment to figure these out. One thing to note: if the first 'nybble'
  is greater than 0x7, the background will be in a raised intensity, and in W9X, if the console
  is set to full screen, the text will flash. The hexadecimal byte described should be passed as
  a DECIMAL integer unless you do some interesting tricks with Lua's string.sub() and tonumber()
  functions. Most of the time the background will be black, so it's easy to specify text colours
  in most cases.


c.bar(Text)

  'Text'        is printed on the console window's title bar.

  A number can be printed. Lua will coerce it to a string. Likewise nil can be printed because
  the C code will detect it and convert it to a literal string "nil".


c.cls()

  This function takes no arguments. It scrolls empty lines to clear the screen. Unlike the normal
  console command CLS, it preserves the Lua command prompt colour, as set by c.cmd().


c.cmd(0xXX)

  '0xXX'        is a integer, but it helps with explanations.

  This works like c.att(), but c.cmd() changes the colour of the command prompt and error reports
  in Lua's interactive mode. This may not be very useful but it's entertaining...


c.cur(0~99)

  '0~99'        is a integer setting the cursor block size.

  If the number is 0, the cursor is not visible, otherwise the block size rises from a line at the
  bottom, to a full block, where the number is a percentage. It's not accurate, but it works. If a
  number less than 0 or greater than 99 is used, it will be clipped to fit the range 0~99.


c.get(Text,Length,Width)

  'Text'        is a string to be edited or replaced by key input.
  'Length'      is a length given to limit input character count.
  [Width]       is an optional limit on characters shown during input.

  The output string is returned, so like string.gsub(), the source is passed in, and the output is
  directed either to the source string, or another string. The internal buffer length is set by the
  MAX_PATH limit because this function is a line editor intended to get a path or command input or
  other short string input by the user. This is at least twice as much as could normally be typed
  on a Windows console's command line.

  It is wise to set length by need. The length argument will do this. If the width argument is not
  provided, it defaults to the same value as the length, so the whole input field is visible unless
  the length would extend beyond the end of the row, in which case it is clipped so it doesn't, and
  it always leaves room for a cursor. The width can be limited to edit long strings in short fields
  for neat text formatting. If the length exceeds the width, the text will scroll as characters are
  entered or deleted.

  As with Lua's interactive mode, backspace deletes the last character, and arrow keys do nothing,
  so deletion alone is possible. Pressing ESC or Ctrl+C will clear the string for new input. If the
  input is cleared, using ESC or Ctrl+C again will abandon the edit and return the original input.

  Avoid using the last line of the screen for input. There are BIOS bugs that cause errors in text
  colour printing. When using c.put(), text is never printed on the last line, but cursor position
  can be placed there, and if you MUST do it, at the very least avoid any use of the bottom corners
  unless you want to explore this to see why this advice matters... It's not harmful, but you won't
  like the results very much. ALL 'x86' machines have BIOS calls that have these faults, and there
  are limits on what can be done to avoid them. Using c.put() is unconditionally safe but using Lua
  print commands, or using c.get(), may not be, so avoid the bottom line unless you need it. Test
  carefully when you use it.


c.pos(X,Y)

  ['X'/'Y']     are optional screen co-ordinates for the cursor.

  If either X or Y are zero or omitted, the function returns two numbers, one for each axis of the
  current cursor position. These can be used to restore a position after using c.get(), to print an
  accepted input in a new colour over the entered text to indicate data entry status, or to allow a
  relative position to be calculated for a new position for another entry or an output message. The
  X and Y positions are on a 1-based scale, and if non-zero values are entered, the cursor is moved
  to the specified location, and no values are returned.

  Any location can be used, and if the integer input is too large it will be safely clipped to fit.
  Take care to read details for c.get() because there are problems with some screen positions. Most
  times it's easy to avoid them especially if you think carefully about formatted text layout.

  A third and fourth value are returned when c.pos() is called without arguments. These are a count
  of characters available in the X and Y axes, i.e. a count of columns and rows, respectively. This
  is useful when deciding whether or not to use word wrap when printing text to a screen, because a
  console can have different line counts or row lengths based on user-set modes, or launch methods,
  and if there are enough lines for the text it is pointless to ask the user to press a key to see
  any more of it.


c.put(Text,Wrap)

  'Text'        is printed to the console with the current colours.
  [Wrap]        is an optional non-nil switch to enable word wrap.

  The text can be a string, or a number, or nil. The expected results will be printed. This is the
  same action as Lua's command print(Text), but with coloured text.

  The text printed by c.put() will normally wrap at the end of a row. If the output is long enough
  to reach the end of the screen it scrolls up one line as it gets to the end before printing, this
  being needed to avoid a BIOS bug, rather than print before scrolling. Another BIOS bug is avoided
  by strict limiting at the end of a row if no other line break occurs first. This function is also
  modified by the c.wrp() setting, described below.

  If wrap is on, the lines break on word breaks, but also, if the end of the screen is reached, the
  printing pauses, waiting for a key to be pressed. Most key presses will cause a screen wipe, with
  the next printing starting at the top, but pressing ESC or Ctrl+C will immediately stop and show
  the prompt at the bottom of the most recently printed text.

  WARNING: The Lua print() function is complex, it can chain several comma-separated objects as one
  string, and can be useful when developing code, but that complexity is slow, and c.put() is very
  fast. If mixing both methods, this can result in weirdness! Two c.put() prints may occur in close
  succession, and a diagnostic print(), inserted between them somewhere, will result in the print()
  output appearing AFTER the second c.put()! This can cause misdiagnosis of a problem, by appearing
  to indicate it originates somewhere later than it really does! To avoid this, DO NOT mix methods.
  Either use c.put() or print() but never both. It may be wise to use print() while developing, and
  when the program does what it should, change to c.put if you want to use coloured text. The delay
  in print() output may not always occur, it may depend on how long certain things take to run, or
  on whether the print is to the console, or is redirected to a file, and fast sequential operation
  is guaranteed by using c.put(), but using it can be less convenient than using print() because a
  line of text may need formatting in advance. Using c.put() makes sure that text is always written
  directly and immediately and in the order intended.




----------------------------------------------------------------------------------------------------

FILE


f.chk(Name)

  'Name'        is the name of a file that may or may not exist.

  The check function returns the size of the file if it succeeded, or nil/false if the file does
  not exist. This function can only check one file at a time.


f.pne(Table,Path,Attr)

  'Table'       is an empty table to be filled with path text.
  'Path'        is a path to a file or directory to be tested.
  [Attr]        is a non-nil request to return file attributes.

  The f.pne() function takes a path in mixed long or short node names, and tests if it points to a
  valid entity in the file system. If there is one, the empty table is filled with long and short
  forms of its path and its name and its extension if the final node in the original path is valid.
  The return value is 0/1/2=Invalid/File/Dir. If R is not nil or omitted, f.pne() returns standard
  Windows file attributes.

  If the file or directory indicated by path is valid, a table 'T' will have 6 values as described:
  T.lp is the long-name path, T.ln is the long filename and T.le is the long form of its extension.
  T.sp, T.sn, and T.se are the DOS '8.3' short name forms of the same path data with any tildes '~'
  being correctly set to match the data in the file system.

  If the file or directory indicated by path is NOT valid it is important to check the return value
  but there will still be data in the table. Path and name data will indicate the last valid node,
  which may be important as a diagnostic, or be otherwise useful information in a program.

  The f.chk() function will do a minimal test for validity, but f.pne() is the only way to get path
  data from the file system. This matters because if you want to make a new file type based on the
  long name of an original, dragging and dropping the original onto a command window will pass only
  the short form data or whatever is explicitly written as a command argument. The f.pne() function
  gets everything, including detailed attributes if those are wanted.

  All directory names have a slash after them. This is critical because it is the only way the name
  can indicate that it IS a directory. Files may not have extensions and directories CAN have them,
  so the situation may be dangerously ambiguous at times without this indication, and a slash makes
  it a lot easier to concatenate a directory name with a filename. The return value can be used to
  detect if the object is a file or directory, but this convention can make directory and path text
  easier, safer, and more convenient. A simple concatenation of  T.lp..T.ln..T.le  is enough to get
  the full long-name path to any valid object in the file system, while individual substrings help
  when making alternative arrangements of any paths, files, or extensions used.

  Detecting bits in the attribute value can be based on the second return of a.div(). This is a way
  to get consistent 'mod' operation in all three versions of Lua used by LuaTools. Unless a minimal
  bit function is added to LuaTools, the methods to iterate or detect bits must be written in Lua.


f.ren(OldName,NewName)

  'OldName'     is the name of a file that must already exist.
  'NewName'     is the name intended to replace the old name.

  The rename function returns 1/true if it succeeded, or nil/false if it failed. Any attempt to
  rename an absent file will fail. This function cannot rename more than one file at a time.


f.del(Name,Wipe)

  'Name'        is the name of a file that must already exist.
  [Wipe]        is an optional flag. Wipe=1 causes file shredding.

  The delete function returns 1/true if it succeeded, or nil/false if it failed. Hidden files can
  be deleted, but failure is the result of any attempt to delete absent files or files protected
  by read-only attributes. This function cannot delete more than one file at a time.

  If the wipe flag is set to 1, the file is securely wiped, shredded with random characters before
  deletion. If it has any other value, or is absent, no wiping occurs. When wiping, this function
  makes many checks, on opening, writing, and closing, then deleting the file, and will only report
  success if everything worked. An XORshift method is used to write the file 4 bytes at a time, so
  it's very fast, but on a large file it may still take time. Consider this before trying it.

  WARNING: This will work on a magnetic hard disk because its disk controller firmware will try to
  write to the original sectors, but 'wear levelling' on flash or SSD devices will cause the random
  data to write to a new location! These devices are inherently insecure unless every byte in their
  history was written using encryption. This may be true even for magnetic disks when bad sectors,
  previously filled with unencrypted data, are hidden from the computer by the disk controller if
  it finds them difficult to access. The f.del() wipe ONLY forces a bypass of the operating system
  cache, but this is enough to put it out of reach of ordinary tools and methods of data recovery.


f.get(Name)

  'Name'        is the name of a file that must already exist.

  The get function returns the string of bytes loaded if it succeeded, or nil/false if it failed.
  The entire file is loaded unless something is wrong with it, or with the system hosting it. Use
  f.chk() first to compare its output with the length of string returned by f.get() if success is
  critical. They should be equal. This function loads only one file at a time.


f.put(Name,Data)

  'Name'        is the name of a file that may or may not exist.
  'Data'        is a string of bytes to save to the named file.

  The put function returns the amount of bytes saved if it succeeded, or nil/false if it failed.
  The entire file is replaced unless something is wrong with it, or with the system hosting it. A
  read-only attribute will also cause it to fail, but a hidden file can be replaced. Use f.chk()
  afterwards and compare the returned values if success is critical. They should be equal. This
  function saves only one file at a time.


f.dlg(Title,Filter,Text,Lines,Table)

  'Title'       defaults to 'Open', if an empty string is passed.
  'Filter'      is specified as wxLua does it (see example below).
  'Text'        is up to 1024 characters, printed below the filter field.
  'Lines'       is the count of lines needed to display the text.
  'Table'       is the name of the table Lua will create to hold filenames.

  The selected file count is returned, and the base directory path is placed in table element 0.
  The filenames are placed in table elements 1 onwards, with the following element being nil.
  If the dialog was cancelled without selection, it returns nil, and the named table will also
  be nil if it didn't already exist. If it did exist it will be entirely recreated with new data
  when a selection is made, and the returned number will match that obtained by table.getn().

  Example Lua code for a test script:

  FDF="Code files  (*.c or *.lua)|*.c;*.lua|All files  (*.*)|*.*"
  FDT="This demonstrates a file dialog with two lines of text as a message to state the purpose."
    .."\nThe line count must be specified, with a maximum message length of 1024 characters."
  N=f.dlg("Get Files...",FDF,FDT,2,"X")
  if X then  c.put(X[0])  c.put(X[1])  end  c.msg("File count:",N,0)

  This will print the file count on a messagebox, then print the base directory path immediately
  followed by the first filename as a full file path.

  The title and text can be a string, or a number, or nil. The expected results will be printed.
  The filter's need for a double terminator is covered by the C code, it's unconditionally safe.
  The text string and the buffer for returned path and filenames are also unconditionally safe.
  The worst that could happen is if a large number of files with very long names is called for,
  the result is that not all of them will get processed. The buffer holds up to 32767 characters,
  enough for a file path up to 256 characters long, followed by up to 255 filenames, each averaging
  126 characters. Not many situations will outrun this, and the buffer is protected from overflow.




----------------------------------------------------------------------------------------------------
